/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions;

import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.GUIDStorage;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.Character;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.stats.StatsFactory;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.SimplePlayer;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Massimo Canonaco
 */
public class SelectCharacterAction implements GenericLogicAction {

	/**It's the value for adding characters without limitations. */
	static private final int UNLIMITED = -1;
	
	/**It's the list of the character who the performer player owns. */
	private List<Character> characterPool;
	
	/**It's the battle player who'll represent the performer during the match. */
	private SimplePlayer warrior;
	
	/**It's the factory for building the statics of the character. */
	private StatsFactory roleBuilder;
	
	/**It's used for checking the maximum value of the match manager for the characters.*/
	private int matchManagerMonitor;
	
	/** */
	static public final float GUID = GUIDStorage.SELECT_CHARACTER_ACTION;
	
	public SelectCharacterAction(final List<Character> pool, final SimplePlayer player, final StatsFactory roles)
	{
		characterPool = pool;
		warrior = player;
		roleBuilder = roles;
		matchManagerMonitor = UNLIMITED;
	}
	
	public SelectCharacterAction(final List<Character> pool, final SimplePlayer player, final StatsFactory roles, final int max)
	{
		characterPool = pool;
		warrior = player;
		roleBuilder = roles;
		matchManagerMonitor = max;
	}
	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.Action#getActionIdentifier()
	 */
	@Override
	public float getActionIdentifier() 
	{
		return GUID;
	}

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.Action#execute(java.util.LinkedList)
	 */
	@Override
	//TODO: signal new character has been added.
	//TODO: signal the character has been removed or the list is full of characters.
	public boolean execute(LinkedList<GenericActionInfo> infos) 
	{
		GenericActionInfo gai = null;
		Character aci = null;
		Iterator<GenericActionInfo> iterator = infos.iterator();
		
		// Looking through each information.
		while (iterator.hasNext()) 
		{
			gai = iterator.next();
			// If it's an AddCharacterInfo.
			if(gai.getGUID() == AddCharacterInfo.GUID)
			{
				// Remove the information from the list.
				iterator.remove();
				
				// Get the character.
				aci = ((AddCharacterInfo) gai).getCharacter();
				// If it's an "add" action and the list isn't full.
				if(isAdd(aci) && (matchManagerMonitor > warrior.getCharacters().size() || matchManagerMonitor == SelectCharacterAction.UNLIMITED))
				{
					// Look if the performer player owns that character.
					for (Character chrct : characterPool) 
					{
						// If the character is owned.
						if(chrct == aci)
						{
							// Set the alive attribute.
							chrct.setAlive(true);

							// Re-build the role statics.
							//they can be changed (cause a level up or because the character fought before or GameManager make them null for being more lightweight).
							chrct.setStats(roleBuilder.levellingRole(chrct.getStats().getName(), chrct.getLevel()));

							// Add to the warrior of the battle character.
							warrior.addCharacter(chrct);
						}
					}
					// Free the information.
					gai.setBusy(false);
				}
			}
		}
		return true;
	}

	/**Checks if the passed character isn't contained yet into the <i>warrior</i>'s list. If character is already into that list, so it's a "remove" action.
	 * @param character			is the character that we want add/remove into the <i>warrior</i>'s list.
	 * @return True, the character isn't already into the list so it's a "add" action. False, the character is already into the list so it's "remove" action and he has been removed. */
	private boolean isAdd(Character character) {
		Iterator<Character> iterator = warrior.getCharacters().iterator();
		Character temp = null;
		
		// Look through the warrior's character list.
		while(iterator.hasNext())
		{
			// Get the character.
			temp = iterator.next();
			
			// If the character is already in.
			if(temp == character)
			{
				// Remove from the list and return false.
				iterator.remove();
				return false;
			}
		}
		
		// Character isn't into the warrior's list, so return true.
		return true;
	}
	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.Action#reset()
	 */
	@Override
	public void reset() {
	}

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.Action#isFinished()
	 */
	@Override
	public boolean isFinished() {
		return true;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return null;
	}

}
